package com.apes.fn.server.servicePlan.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.business.fixedLoss.modle.LossQuotation;
import com.apes.fn.business.fixedLoss.repository.LossQuotationRepository;
import com.apes.fn.business.fixedLoss.service.LossQuotationService;
import com.apes.fn.crm.customer.FnAppCustomerService;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.fn.crm.customerExpand.FnCustomerExpandRepository;
import com.apes.fn.mdm.purchase.PurchasingGroupRepository;
import com.apes.fn.mdm.supplierConfiguration.SupplierBusinessScope;
import com.apes.fn.mdm.supplierConfiguration.SupplierBusinessScopeRepository;
import com.apes.fn.mdm.supplierConfiguration.SupplierBusinessScopeService;
import com.apes.fn.pi.fnCommunal.FnCommunalService;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.repository.ServicePlanRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.repository.ContractRepository;
import com.apes.scm.masterdata.car.model.CarConfiguration;
import com.apes.scm.masterdata.car.repository.CarConfigurationRepository;
import com.apes.scm.masterdata.enumeration.model.BusinessParam;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.enumeration.repository.BusinessParamRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.model.Store;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.frame.repository.StoreRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.Category;
import com.apes.scm.masterdata.product.model.Classify;
import com.apes.scm.masterdata.product.repository.CategoryDao;
import com.apes.scm.masterdata.product.repository.CategoryRepository;
import com.apes.scm.masterdata.product.repository.ClassifyRepository;
import com.apes.scm.rbac.model.User;
import com.apes.scm.rbac.repository.PostRepository;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：询价发起服务
 *
 * @ClassName FnEnquiryService
 * @Description 描述
 * @Author wushilong
 * @Date 2023/3/22 16:07
 * @Version 1.0
 */
@Service
public class FnEnquiryService extends DomainService {

    @Autowired
    private StoreRepository storeRepository;

    @Autowired
    private SupplierBusinessScopeService supplierBusinessScopeService;

    @Autowired
    private ServicePlanRepository servicePlanRepository;

    @Autowired
    private LossQuotationRepository lossQuotationRepository;

    @Autowired
    private PartyRoleRepository partyRoleRepository;

    @Autowired
    private ContractRepository contractRepository;

    @Autowired
    private SupplierBusinessScopeRepository supplierBusinessScopeRepository;

    @Autowired
    private ServicePlanceService servicePlanceService;

    @Autowired
    private LossQuotationService lossQuotationService;

    @Autowired
    private TyreEnquiryService tyreEnquiryService;

    @Autowired
    private CategoryRepository categoryRepository;

    private List<SupplierBusinessScope> supplierBusinessScopes;

    /**
     * 向供应商平台发起询价
     * @param param 询价参数
     */
    private void deptEnquiry(JSONObject param) {
        if (Objects.isNull(param) || param.isEmpty()) return;
        //向供应商询价平台发起询价
        invoke("sp.enquiryService.enquiry", param);
    }

    /**
     * 服务方案单转询价入口
     * @param request
     * @return
     */
    public ServicePlan enquiryService(SimpleRequest request){
        String id = request.getJO().getString("id");
        enquiry(request);
        return servicePlanRepository.findOne(id);
    }

    /**
     * 定损报价单转询价入口
     * @param request
     * @return
     */
    public LossQuotation enquiryLoss(SimpleRequest request){
        String id = request.getJO().getString("id");
        enquiry(request);
        return lossQuotationRepository.findOne(id);
    }

    /**
     * 译码询价（询价单）
     * @param request
     */
    public boolean enquiry(SimpleRequest request){
        JSONObject requestJO = request.getJO();


        //校验是否可以询价
        Dept dept = selectDept(request);//获取业务单据门店或者是做单门店
        if (Objects.isNull(dept))throw new RuntimeException("非门店角色岗位不能询价！");

        JSONObject customerCar = requestJO.getJSONObject("customerCar");
        User user = request.getCurrentUser();

        //客户车辆信息
        List<FnCustomerExpand> fnCustomerExpands = getBean(FnCustomerExpandRepository.class).findAllByCarLicenseAndVendorCode(customerCar.getString("carLicense"), customerCar.getString("vendorCode"));
        if (fnCustomerExpands.isEmpty()) throw new RuntimeException("车牌："+ customerCar.getString("carLicense") +"在"+ dept.getName()
                +"无车辆信息，需"+ dept.getName() +"完成建档后 [发布询价]");
        FnCustomerExpand fnCustomerExpand = fnCustomerExpands.stream().filter(item -> StringUtils.isNotEmpty(item.getJekunModelCode())).findFirst().get();

        //国产车没有上传图片不允许询价
        getBean(AbstractPlan.class).checkCarInformation(fnCustomerExpand);

        CarConfiguration carConfiguration = getBean(CarConfigurationRepository.class).findOne(fnCustomerExpand.getJekunModelCode());

        //询价分类
        Map<String, JSONArray> typeTag = requestJO.getJSONArray("partsList").stream().collect(Collectors.groupingBy(item -> ((JSONObject) item).getString("typeTag"), Collectors.toCollection(JSONArray::new)));

        //处理询价配件
        JSONArray partsList = getCategoryItem(typeTag.get("common"));

        //处理询价轮胎
        JSONArray tyreList = tyreEnquiryService.getTyreItem(typeTag.get("tyre"));

        //处理改装配件
        JSONArray refitList = getRefitCategoryItem(typeTag.get("refit"));

        //获取询价参数
        JSONObject categoryParam = getParam(requestJO.getString("id"), fnCustomerExpand, carConfiguration, dept, user, request, partsList, "common");
        JSONObject tyreParam = getParam(requestJO.getString("id"), fnCustomerExpand, carConfiguration, dept, user, request, tyreList, "tyre");
        JSONObject refitParam = getParam(requestJO.getString("id"), fnCustomerExpand, carConfiguration, dept, user, request, refitList, "refit");

        JSONObject param = new JSONObject(MapUtil.mapper("categoryParam", categoryParam, "tyreParam", tyreParam, "refitParam", refitParam));

        //记录业务单据日志（服务/定损）
        addServicePlanLogger( requestJO.getString("id"), user, request);

        //向供应商平台发起询价
        deptEnquiry(param);

        return true;
    }

    private void addServicePlanLogger(String id, User user, SimpleRequest request){
        if (StringUtils.isEmpty(id)) return;
        if (id.startsWith("FW")){
            ServicePlan servicePlan = servicePlanRepository.findOne(id);
            servicePlanceService.addServicePlanLogger( servicePlan,"发布询价","",user);
            //转询价时间
            servicePlanceService.setInquiryDetail(request,servicePlan,"toInquiry");
            servicePlanRepository.saveAndFlush(servicePlan);
        }
        if (id.startsWith("DS")){
            LossQuotation lossQuotation = lossQuotationRepository.findOne(id);
            servicePlanceService.addServicePlanLogger( lossQuotation,"发布询价","",user);
            //转询价时间
            lossQuotationService.setToInquiryInfo(request,lossQuotation);
            lossQuotationRepository.saveAndFlush(lossQuotation);
        }

    }

    /**
     * 获取业务单据门店或者是做单门店
     * @param request
     * @return
     */
    private Dept selectDept(SimpleRequest request){
        JSONObject requestJO = request.getJO();
        String id = requestJO.getString("id");
        if (StringUtils.isEmpty(id)){
            return getBean(PostRepository.class).findOne(request.getPostId()).getDept();
        }
        if (id.startsWith("FW")){
            return servicePlanRepository.findOne(id).getBelongDept();
        }
        if (id.startsWith("DS")){
            LossQuotation lossQuotation = lossQuotationRepository.findOne(id);
            return lossQuotation.findWorkDept();
        }
        return getBean(PostRepository.class).findOne(request.getPostId()).getDept();
    }

    /**
     * 处理询价配件
     * @param array
     * @return
     */
    public JSONArray getCategoryItem(JSONArray array){
        if (Objects.isNull(array) || array.isEmpty()) return null;
        for (int i = 0; i < array.size(); i++) {
            JSONObject parts = array.getJSONObject(i);
            if (parts.containsKey("partsInfos")) {
                parts.put("note", parts.getJSONObject("partsInfos").getString("otherRemark"));
                parts.put("saleQty", 1);
                parts.put("price", parts.getJSONObject("partsInfos").getString("price"));
                parts.put("partCode", parts.getString("partsCodes"));
            }else {
                parts.put("note", parts.getString("note"));
                parts.put("saleQty", parts.getIntValue("saleQty"));
                parts.put("price", parts.getString("price"));
                parts.put("partCode", parts.getString("partCode"));
            }
            parts.put("oldPicture", disposeImg(parts));
            //拼接本地域名到图片地址
            getThisPicture(parts);
            //获取标准配件
            putCategory(parts);

            parts.put("id",i);
        }
        return array;
    }

    //拼接本地域名到图片地址（给外部系统询价使用）
    private void getThisPicture(JSONObject parts) {
        if (parts.containsKey("thisPicture")){
            String host = getBean(BusinessParamRepository.class).findOne("21").getValue();//21:表示域名
            JSONArray urls = new JSONArray();
            parts.getJSONArray("thisPicture").toJavaList(JSONObject.class).forEach(item -> {
                String url = host + item.getString("url");
                urls.add(url);
            });
            parts.put("thisPicture", urls);
        }
    }

    /* 获取标准配件*/
    private void putCategory(JSONObject parts) {
        String categoryId = getBean(CategoryDao.class).getCategoryId(parts.getString("standardName"));
        Category categoryName = categoryRepository.findByName(parts.getString("standardName"));
        if (Objects.nonNull(categoryName)){
            parts.put("category", categoryName);
        }
        if (StringUtils.isNotEmpty(categoryId) && Objects.isNull(categoryName)){
            categoryName = categoryRepository.findOne(categoryId);
            parts.put("category", categoryName);
        }
        if (StringUtils.isEmpty(categoryId) && Objects.isNull(categoryName) && parts.containsKey("category")) {
            categoryName = categoryRepository.findOne(parts.getJSONObject("category").getString("id"));
            parts.put("category", categoryName);
        }
        if (StringUtils.isEmpty(categoryId) && Objects.isNull(categoryName)){
            Category category = new Category();
            category.setName(StringUtils.isEmpty(parts.getString("standardName")) ? parts.getString("value") : parts.getString("standardName"));
            category.setClassify(getBean(ClassifyRepository.class).findOne("M01030501001"));
            category.setValid(true);
            category.setMatchColor(false);
            category.setMatchCProduct(false);
            category.setCategoryPhotos("[]");
            parts.put("category", category);
        }
    }

    /* 处理图片格式*/
    private JSONArray disposeImg(JSONObject parts){
        JSONArray otherImg = new JSONArray();
        JSONArray pictures = new JSONArray();
        if (parts.containsKey("partsInfos")){
            pictures = parts.getJSONObject("partsInfos").getJSONArray("pictures");
            otherImg = parts.getJSONObject("partsInfos").getJSONArray("otherImg");
        }else {
            pictures = parts.getJSONArray("epcPicture");
            otherImg = parts.getJSONArray("oldPicture");
        }
        if (otherImg != null && !otherImg.isEmpty() && pictures != null) {
            pictures.addAll(otherImg);
        }
        //线上环境图片地址
        if (otherImg != null && !otherImg.isEmpty() && "pro".equals(getBean(BusinessParamRepository.class).findOne("20").getValue())) {
            otherImg.forEach(o -> {
                JSONObject item = (JSONObject) o;
                if (StringUtils.isNotEmpty(item.getString("thumbUrl")) ) {
                    item.put("url", "https://fnhq.jekunauto.com/erp/" + item.getString("thumbUrl"));
                }
            });
        }
        return pictures == null ? otherImg : pictures;
    }

    /**
     * 处理精品改装询价
     * @param array
     * @return
     */
    public JSONArray getRefitCategoryItem(JSONArray array){
        if (Objects.isNull(array) || array.isEmpty()) return null;
        for (int i = 0; i < array.size(); i++) {
            JSONObject parts = array.getJSONObject(i);
            String note = parts.getString("note");
            if (StringUtils.isEmpty(note) || !note.contains("带安")){
                note = "带安";
            }
            parts.put("note", note);
            parts.put("saleQty", parts.getIntValue("saleQty"));
//            parts.put("partCode", parts.getString("partsCodes"));
            parts.put("partCode", parts.getString("productName"));

            parts.put("oldPicture", disposeImg(parts));
            Category category = parts.getJSONObject("category").toJavaObject(Category.class);
            if (Objects.isNull(category)){
                category = new Category();
                category.setName(parts.getString("value"));
                category.setClassify(getBean(ClassifyRepository.class).findOne("M0102"));
                category.setValid(true);
                category.setMatchColor(false);
                category.setMatchCProduct(false);
                category.setCategoryPhotos("[]");
                parts.put("category", category);
            } else {
                parts.put("category", category);
            }

            parts.put("id",i);
        }
        return array;
    }

    /**
     * 构建询价参数
     * @param id 单据号码
     * @param fnCustomerExpand 赋能客户信息
     * @param carConfiguration 车型信息
     * @param saleDept 门店
     * @param user 用户
     * @param request 请求对象(没有取值)
     * @param object 单据对象
     * @return
     */
    private JSONObject getParam(String id, FnCustomerExpand fnCustomerExpand, CarConfiguration carConfiguration, Dept saleDept,
                                User user, SimpleRequest request, Object object, String categoryType) {
        if (Objects.isNull(carConfiguration) || Objects.isNull(object)) return null;
        //初始化急件供应商
        supplierBusinessScopes = new ArrayList<>();

        //初始化询价数据
        JSONObject param = new JSONObject();
        //是否开票
        List<BusinessParam> businessParams = getBean(BusinessParamRepository.class).accordingToCompanyContract(Arrays.asList(saleDept.getCompany().getId()));
        boolean beInvoice = businessParams.size() != 0;
        if (businessParams.size() != 0){
            BusinessParam businessParam = businessParams.stream().findFirst().get();
            PartyRole company = getBean(PartyRoleRepository.class).findOne(businessParam.getValue());
            beInvoice = company.getParty().getCorporate().isWantInvoice();
        }else {
            beInvoice = saleDept.getCompany().getParty().getCorporate().isWantInvoice();
        }
        param.put("beInvoice", beInvoice);
        param.put("servicePlan", id);//来源单据
        param.put("fnCustomerExpand", MapUtil.mapped(fnCustomerExpand));//客户赋能扩展表
        param.put("fnCustomer", MapUtil.mapped(carConfiguration));//配置车型
        Store store = storeRepository.findOne(saleDept.getId());
        param.put("store", MapUtil.mapped(store));//门店详细信息
        param.put("employee", MapUtil.mapped(user));//联系人
        param.put("carLabel", MapUtil.mapped(carConfiguration.getCarLabel()));//厂牌
        param.put("carModel", MapUtil.mapped(carConfiguration.getCarModel()));//车型

        //根据配件明细确定供应商
        categoryArray(saleDept, object, param,beInvoice,request, categoryType);

        //车头、车尾、铭牌照片
        request.setData(MapUtil.mapper("carLicense", fnCustomerExpand.getCarLicense(), "vendorCode", fnCustomerExpand.getVendorCode()));
        param.put("pictures", getBean(FnAppCustomerService.class).getPictures(request));
        param.put("origin",saleDept.getOrigin());
        PartyRole platform = SpringManager.getBean(FnCommunalService.class).getPlatform(false, true, saleDept);
        param.put("platform",JSONObject.toJSONString(platform));
        return param;
    }

    /**
     * 根据配件明细确定供应商
     * @param saleDept 门店
     * @param object 单据来源
     * @param param 询价参数
     */
    private void categoryArray(Dept saleDept, Object object, JSONObject param,boolean beInvoice,SimpleRequest request, String categoryType) {
        JSONArray categoryArray = (JSONArray) object;
        param.put("categoryItem", MapUtil.mapped(categoryArray));//明细
        //获取询价供应商id列表
        Enumeration enumeration =  saleDept.getCompany().getParty().getCorporate().getOperation();
        List<String> filterSupplierId = getSupplierId(param.getJSONObject("carLabel").getString("id"), saleDept);
        List<String> supplierIdList = verifyContract(filterSupplierId, beInvoice, categoryType);
        supplierIdList = isPush(supplierIdList,enumeration);
        if (supplierIdList.isEmpty()) throw new RuntimeException("请检查当前门店是否配置采购组或者供应商！");
        //根据供应商经营品类分发
        param.put("supplierAndCategories", categoryEnquiryList(categoryArray, supplierIdList));
    }


    /**
     *判断供应商是否推单
     * @param supplierIdList
     * @param enumeration  直营:001072;合伙人:001071;赋能店:001073;直营子公司:001661;
     * @return
     */
    public List<String> isPush(List<String> supplierIdList, Enumeration enumeration){
        List<String> supplierIds = new ArrayList<>();
        supplierIdList.stream().forEach(e->{
            List<Contract> contracts = contractRepository.findValidPlatformSupplierState(partyRoleRepository.findOne(e));//合同
            List<Contract> agreements = contractRepository.findValidPlatformState(partyRoleRepository.findOne(e));//协议
            int contractSize = contracts.size();
            int agreementSize = agreements.size();
            String type = enumeration.getId();
            if("001073".equals(type)&&agreementSize>0 && contractSize<=0){
                supplierIds.add(e);
            }
            if(("001072".equals(type)|| "001661".equals(type))&&contractSize>0 && agreementSize<=0){
                supplierIds.add(e);
            }
            if(contractSize>0 && agreementSize>0){
                supplierIds.add(e);
            }
        });
        return supplierIds;
    }

    /**
     *校验供应商合同协议
     * @param suppilerList
     * @param beInvoice
     * @return
     */
    public List<String> verifyContract(List<String> suppilerList, boolean beInvoice, String categoryType){
            List<String> list = new ArrayList<>();
        for (String  id:suppilerList) {
            PartyRole supplier = partyRoleRepository.findValidSupplier(id, null);
            List<Contract> contracts;
            if (beInvoice) {
                contracts = SpringManager.getBean(ContractRepository.class).findValidPlatformSupplierState(supplier);
            } else {
                contracts = SpringManager.getBean(ContractRepository.class).findValidPlatformState(supplier);
            }
            if (contracts != null || contracts.size() != 0) {
                if ("refit".equals(categoryType)) { // 是否带安判断
                    List<Contract> consignInstallContracts =  contracts.stream().filter(contract -> contract.isConsignInstall()).collect(Collectors.toList());
                    if (!consignInstallContracts.isEmpty()) list.add(id);
                } else {
                    list.add(id);
                }

            }
        }

        return list;
    }


    //获取询价供应商id列表
    private List<String> getSupplierId(String carLabelId, Dept saleDept) {
        //根据采购组确定供应商
        List<String> suppliers = getBean(PurchasingGroupRepository.class).accordingToDeptGetSupplierId(saleDept.getId());
        //根据供应商经营厂牌排除供应商
        return suppliers.stream().filter(supplier -> supplierBusinessScopeService.isOperationTime(supplier)).filter(supplier -> supplierBusinessScopeService.
                ifSupplierBusinessScope(supplier, carLabelId)).collect(Collectors.toList());
    }

    /**
     * 根据供应商确定经营配件
     * 定损报价单
     * @param categoryArray 询价配件明细
     * @param filterSupplierId 通过厂牌过滤后的供应商
     * @return 每个供应商对应的配件
     */
    private List<JSONObject> categoryEnquiryList(JSONArray categoryArray, List<String> filterSupplierId) {
        List<JSONObject> supplierAndCategories = new ArrayList<>();
        for (Object o : categoryArray) {
            JSONObject category = (JSONObject) o;
            //缓存急件供应商（查询慢）
            if (supplierBusinessScopes.isEmpty()){
                supplierBusinessScopes = supplierBusinessScopeRepository.accordingSupplierFind(filterSupplierId);
            }
            //根据供应商经营范围推单
            for (SupplierBusinessScope supplierBusinessScope : supplierBusinessScopes) {
                Classify classify = getBean(ClassifyRepository.class).findOne(((Category)category.get("category")).getClassify().getId());
                //查询供应商经营品类，没有配置则是全部经营
                if (!supplierBusinessScopeService.ifExcludeOfClassify(supplierBusinessScope, classify))
                    continue;
                if (supplierBusinessScopeService.ifSupplierRunClassify(supplierBusinessScope, classify)) {
                    JSONObject supplierAndCategory = new JSONObject();
                    supplierAndCategory.put("supplierId", supplierBusinessScope.getSupplierId().getId());
                    supplierAndCategory.put("serviceItem", MapUtil.mapped(category));
                    supplierAndCategories.add(supplierAndCategory);
                }
            }
        }
        return supplierAndCategories;
    }

    /**
     * 获取供应商票点
     *
     * @param request
     * @return
     */
    public Double getSupplierTicketPoint(SimpleRequest request) {
        JSONObject requestJO = request.getJO();
        String id = requestJO.getString("store");
        Dept dept = getBean(DeptRepository.class).findOne(id);

        String supplierId = requestJO.getString("supplierId");
        String brandId = requestJO.getString("brand");
        return getBean(PriceForwardService.class).getSupplierTicketPoint(dept.getCompany().getId(), supplierId, brandId, null);
    }
}
